﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using PhotoGallery.Repositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Authentication.Cookies;
using PhotoGallery.Models;
using Microsoft.EntityFrameworkCore;
using PhotoGallery.Utils;
using System.Security.Claims;
using Microsoft.Extensions.Primitives;

namespace PhotoGallery.Controllers
{
    public class MemberController : Controller
    {
        private IConfiguration _config;
        private PhotoGalleryRepository _repo;
        //private HttpContextAccessor _httpContextAccessor;
        public MemberController(IConfiguration config, 
            PhotoGalleryRepository repo)
        {
            _config = config;
            _repo = repo;
            //_httpContextAccessor = httpContextAccessor;
        }
        

        [HttpGet]
        [AllowAnonymous]
        public async Task<IActionResult> Login(string returnUrl = null)
        {
            if (HttpContext.Request.Query.Any(q => q.Key == "logout") && User.Identity.IsAuthenticated)
            {
                await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                
            }
            ViewData["ReturnUrl"] = returnUrl;
            return View();

        }

    
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model,string returnUrl)
        {
            ViewData["ReturnUrl"] = returnUrl;
            var message = "";
            if (ModelState.IsValid)
            {
                try
                {
                    var usr = _repo.Users.IgnoreQueryFilters().FirstOrDefault(w => w.UserName == model.UserName);
                    if (usr == null)
                    {
                        message = "用户不存在";
                    }
                    else
                    {
                        if (!usr.IsEnable)
                        {
                            message = "账户被锁定,请联系管理员解锁";                           
                        }
                        else
                        {
                            if (LoginHelper.VerifyHashedPassword(model.Password, usr.PasswdHash, usr.Salt))
                            {

                                usr.FailRetry = 0;
                                usr.LastLoginTime = DateTime.Now;
                                var remoteIP = Request.HttpContext.Connection.RemoteIpAddress.ToString();
                                Console.WriteLine("RemoteIP:" + remoteIP);
                                //if (string.IsNullOrEmpty(remoteIP) || remoteIP.Contains("127.0.0.1"))
                                //{
                                //    remoteIP = GetRequestIP();
                                //}
                                
                                usr.LastLoginIP = remoteIP;
                                _repo.Update(usr);
                                _repo.SaveChanges();

                                var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                                identity.AddClaim(new Claim(ClaimTypes.Name, usr.UserName));

                                var principle = new ClaimsPrincipal(identity);
                                var properties = new AuthenticationProperties { IsPersistent = model.Remember };
                                await HttpContext.SignInAsync(principle, properties);

                                return Redirect("~/");
                            }
                            else
                            {
                                message = "密码错误";
                                var failCount = 0;
                                int.TryParse(_config["user:MaxFailCount"], out failCount);
                                if (usr.FailRetry < failCount)
                                {
                                    usr.FailRetry += 1;
                                }
                                else
                                {
                                    usr.IsEnable = false;
                                    message = "密码输入错误次数太多,已被锁定";
                                }
                                _repo.Update(usr);
                                _repo.SaveChanges();
                            }
                        }
                        
                    }
                  
                }
                catch
                {
                    message = "登陆异常,请重试.";
                }
                ModelState.AddModelError(string.Empty, message);               
            }
            return View(model);
            
        }


        public async Task<IActionResult> Logout()
        {
            if (User.Identity.IsAuthenticated)
            {
                await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            }
            return Redirect("~/");

        }

        private IActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return Redirect("~");
            }
        }

        /*
        public string GetRequestIP(bool tryUseXForwardHeader = true)
        {
            string ip = null;

            // todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For

            // X-Forwarded-For (csv list):  Using the First entry in the list seems to work
            // for 99% of cases however it has been suggested that a better (although tedious)
            // approach might be to read each IP from right to left and use the first public IP.
            // http://stackoverflow.com/a/43554000/538763
            //
            if (tryUseXForwardHeader)
                ip = GetHeaderValueAs<string>("X-Forwarded-For").SplitCsv().FirstOrDefault();

            // RemoteIpAddress is always null in DNX RC1 Update1 (bug).
            if (ip.IsNullOrWhitespace() && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)
                ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

            if (ip.IsNullOrWhitespace())
                ip = GetHeaderValueAs<string>("REMOTE_ADDR");

            // _httpContextAccessor.HttpContext?.Request?.Host this is the local host.

            if (ip.IsNullOrWhitespace())
                throw new Exception("Unable to determine caller's IP.");

            return ip;
        }

        public T GetHeaderValueAs<T>(string headerName)
        {
            StringValues values;

            if (_httpContextAccessor.HttpContext?.Request?.Headers?.TryGetValue(headerName, out values) ?? false)
            {
                string rawValues = values.ToString();   // writes out as Csv when there are multiple.

                if (!string.IsNullOrEmpty(rawValues))
                    return (T)Convert.ChangeType(values.ToString(), typeof(T));
            }
            return default(T);
        }
        */
    

    }
}